#include "DekkoGlobal.h"
#include <QtQuick>
#include <QQmlContext>
#include <QtQml/QtQml>
#include "Common/Application.h"
#include "Common/MetaTypes.h"
#include "Common/SettingsNames.h"
#include "3rdParty/trojita/Imap/Model/FullMessageCombiner.h"
#include "app/Composition/ReplyMode.h"
#include "app/Components/ImageHelper.h"
#include "app/Components/qlimitproxymodelqml.h"
#include "app/Contacts/ContactsModel.h"
#include "app/Contacts/ContactFilterModel.h"
#include "app/Contacts/FlattenContactModel.h"
#include "app/Contacts/CombinedFlattenContactModel.h"
#include "app/Contacts/CombinedFlattenContactFilterModel.h"
#include "app/Accounts/Account.h"
#include "app/Accounts/AccountsManager.h"
#include "app/Accounts/PasswordManager.h"
#include "app/Models/AccountsListModel.h"
#include "app/Accounts/SenderIdentity.h"
#include "app/Accounts/SenderIdentityModel.h"
#include "app/Accounts/MultipleAccountSenderIdentityModel.h"
#include "app/Composition/SubmissionManager.h"
#include "app/MailConfig/AutoConfig.h"
#include "app/MailConfig/MailConfig.h"
#include "app/MailConfig/ImapSettingVerifier.h"
#include "app/Models/OneThreadMsgListModel.h"
#include "app/Models/MessageListModel.h"
#include "app/Models/MessageListFilterModel.h"
#include "app/Models/MessageModel.h"
#include "app/Models/PreSetProviderModel.h"
#include "app/Models/MailboxProxyModel.h"
#include "app/Models/MailboxFilterModel.h"
#include "app/Settings/Settings.h"
#include "app/Settings/GlobalSettings.h"
#include "app/Settings/ViewSettings.h"
//#include "app/Utils/AttachmentDownloader.h"
#include "app/Utils/Path.h"
#include "app/Utils/PlainTextFormatter.h"
#include "app/Utils/TabEventSignaler.h"
#include "app/Utils/MailboxSearch.h"
#include "app/Utils/MailboxUtils.h"
#include "app/Utils/UidIterator.h"
#include "app/Utils/SearchForSpecialMailbox.h"
#include "app/Utils/EmailValidator.h"
#include "app/Theme/Theme.h"
#include "app/Network/MsgPartNetAccessManagerFactory.h"
#include "Imap/Model/ThreadingMsgListModel.h"
#include "Imap/Model/kdeui-itemviews/kdescendantsproxymodel.h"
#include "app/Settings/MailboxSettings.h"
#include "app/Settings/SettingsFileBase.h"
#include "app/Settings/NotificationSettings.h"
#include "app/Notifications/NotificationService.h"
#include "app/Notifications/PostalServiceWorker.h"
#include "app/OnlineAccounts/OnlineAccountsService.h"
#include "app/Components/OxideWrapper.h"
#include "app/Models/ImapLogModel.h"
#include "app/Composition/Composer.h"

void DekkoGlobal::registerDekkoTypes(const char *uri, int major, int minor)
{
    qDebug() << "Registering " << uri << "types";
    Common::registerMetaTypes();
    registerDekkoAccounts(major, minor);
    registerDekkoComponents(major, minor);
    registerDekkoComposition(major, minor);
    registerDekkoContacts(major, minor);
    registerDekkoExperimental(major, minor);
    registerDekkoModels(major, minor);
    registerDekkoSettings(major, minor);
    registerDekkoUtils(major, minor);
    registerDekkoTheme(major, minor);
}

void DekkoGlobal::registerTrojitaCoreTypes(const char *uri, int major, int minor)
{
    // @uri TrojitaCore
    qmlRegisterUncreatableType<Imap::Mailbox::ThreadingMsgListModel>(uri, major, minor, "ThreadingMsgListModel",
            QStringLiteral("ThreadingMsgListModel can only be created from the C++ code.\
                          Use ImapAccess if you need access to an instance."));
    qmlRegisterSingletonType<UiUtils::Formatting>(uri, major, minor, "UiFormatting", UiUtils::Formatting::factory);
    qmlRegisterUncreatableType<Composer::Submission>(uri, major, minor, "SubmissionMethod",
            QStringLiteral("Composer::Submission::Method can be only created from the C++ code."));
    qmlRegisterUncreatableType<UiUtils::PasswordWatcher>(uri, major, minor, "PasswordWatcher",
            QStringLiteral("PasswordWatcher can only be created from the C++ code. Use ImapAccess\
                           if you need access to an instance."));
}

void DekkoGlobal::registerDekkoModels(int major, int minor)
{
    // @uri Dekko.Models
    const char* uri = "Dekko.Models";
    qmlRegisterType<Dekko::Models::PreSetProviderModel>(uri, major, minor, "PreSetProvidersModel");
    qmlRegisterType<Dekko::Models::MailboxProxyModel>(uri, major, minor, "MailboxProxyModel");
    qmlRegisterType<Dekko::Models::MailboxFilterModel>(uri, major, minor, "MailboxFilterModel");
    qmlRegisterType<Dekko::Models::MessageListModel>(uri, major, minor, "MessageListModel");
    qmlRegisterType<Dekko::Models::MessageListFilterModel>(uri, major, minor, "MessageListFilterModel");
    qmlRegisterType<Dekko::Models::MessageModel>(uri, major, minor, "MessageModel");
    qmlRegisterType<Dekko::Models::MessageAttachment>(uri, major, minor, "MessageAttachment");
    qmlRegisterType<Dekko::Models::OneThreadMsgListModel>(uri, major, minor, "OneThreadMsgListModel");
    qmlRegisterType<QLimitProxyModelQML>(uri, major, minor, "LimitProxyModel");
    qmlRegisterType<KDescendantsProxyModel>(uri, major, minor, "FlatteningProxyModel");
}

void DekkoGlobal::registerDekkoComponents(int major, int minor)
{
    // @uri Dekko.Components
    const char* uri = "Dekko.Components";
    qmlRegisterType<Dekko::Components::ImageHelper>(uri, major, minor, "ImageHelper");
    qmlRegisterType<OxideOverlay>(uri, major, minor, "OxideOverlay");
    qmlRegisterType<Dekko::ImapLog>(uri, major, minor, "ImapLog");
    qmlRegisterType<Dekko::LogItem>(uri, major, minor, "LogItem");
}

void DekkoGlobal::registerDekkoUtils(int major, int minor)
{
    // @uri Dekko.Utils
    const char* uri = "Dekko.Utils";
    qmlRegisterType<Dekko::Utils::PlainTextFormatter>(uri, major, minor, "PlainTextFormatter");
    qmlRegisterType<Dekko::Utils::MailboxSearch>(uri, major, minor, "MailboxSearch");
    qmlRegisterType<Dekko::Utils::MailboxUtils>(uri, major, minor, "MailboxUtils");
    qmlRegisterType<Dekko::Utils::UidIterator>(uri, major, minor, "UidIterator");
    qmlRegisterType<Dekko::Utils::SearchForSpecialMailbox>(uri, major, minor, "SearchForSpecialMailbox");
    qmlRegisterType<Dekko::AutoConfig>(uri, major, minor, "AutoConfig");
    qmlRegisterType<Dekko::ImapSettingVerifier>(uri, major, minor, "ImapSettingVerifier");
    qmlRegisterType<Imap::Mailbox::FullMessageCombiner>(uri, major, minor, "FullMessageCombiner");
    qmlRegisterSingletonType<Dekko::Utils::TabEventSignaler>(uri, major, minor, "TabEventSignaler", Dekko::Utils::TabEventSignaler::factory);
    qmlRegisterSingletonType<Dekko::EmailValidator>(uri, major, minor, "EmailValidator", Dekko::EmailValidator::factory);
}

void DekkoGlobal::registerDekkoContacts(int major, int minor)
{
    // @uri Dekko.Contacts
    const char* uri = "Dekko.Contacts";
    qmlRegisterType<Dekko::Contacts::ContactsModel>(uri, major, minor, "DekkoContactsModel");
    qmlRegisterType<Dekko::Contacts::ContactFilterModel>(uri, major, minor, "ContactFilterModel");
    qmlRegisterType<Dekko::Contacts::FlattenContactModel>(uri, major, minor, "FlattenContactModel");
    qmlRegisterType<Dekko::Contacts::CombinedFlattenContactFilterModel>(uri, major, minor, "CombinedFlattenContactFilterModel");
    qmlRegisterType<Dekko::Contacts::CombinedFlattenContactModel>(uri, major, minor, "CombinedFlattenContactModel");
}

void DekkoGlobal::registerDekkoSettings(int major, int minor)
{
    // @uri Dekko.Settings
    const char* uri = "Dekko.Settings";
    qmlRegisterType<Dekko::Settings::ImapSettings>(uri, major, minor, "ImapSettings");
    qmlRegisterType<Dekko::Settings::SmtpSettings>(uri, major, minor, "SmtpSettings");
    qmlRegisterType<Dekko::Settings::AccountProfile>(uri, major, minor, "AccountProfile");
    qmlRegisterType<Dekko::Settings::Preferences>(uri, major, minor, "Preferences");
    qmlRegisterType<Dekko::Settings::OfflineSettings>(uri, major, minor, "OfflineSettings");
    qmlRegisterType<Dekko::Settings::DeveloperSettings>(uri, major, minor, "DeveloperSettings");
    qmlRegisterType<Dekko::Settings::UOASettings>(uri, major, minor, "UOASettings");
    qmlRegisterType<Dekko::Settings::MailboxSettings>(uri, major, minor, "MailboxSettings");
    qmlRegisterType<Dekko::Settings::NotificationSettings>(uri, major, minor, "NotificationSettings");
    qmlRegisterType<Dekko::Settings::ViewSettings>(uri, major, minor, "ViewSettings");
    qmlRegisterSingletonType<Dekko::Settings::GlobalSettings>(uri, major, minor, "GlobalSettings", Dekko::Settings::GlobalSettings::factory);

}

void DekkoGlobal::registerDekkoAccounts(int major, int minor)
{
    // @uri Dekko.Accounts
    const char* uri = "Dekko.Accounts";
    qmlRegisterType<Dekko::Models::AccountsListModel>(uri, major, minor, "AccountsListModel");
    qmlRegisterType<Dekko::Accounts::Account>(uri, major, minor, "Account");
    qmlRegisterType<Dekko::Accounts::AccountsManager>(uri, major, minor, "AccountsManager");
    qmlRegisterType<Dekko::Accounts::PasswordManager>(uri, major, minor, "PasswordManager");
    qmlRegisterType<Dekko::Accounts::SenderIdentity>(uri, major, minor, "SenderIdentity");
    qmlRegisterType<Dekko::Accounts::SenderIdentityModel>(uri, major, minor, "SenderIdentityModel");
    qmlRegisterType<Dekko::Accounts::MultipleAccountSenderIdentityModel>(uri, major, minor, "MultipleAccountSenderIdentityModel");
    qmlRegisterUncreatableType<NewAccountType>(uri, major, minor, "NewAccountType", QStringLiteral("Can't create an instance in qml"));
}

void DekkoGlobal::registerDekkoComposition(int major, int minor)
{
    // @uri Dekko.Composition
    const char* uri = "Dekko.Composition";
    qmlRegisterType<Dekko::ReplyMode>(uri, major, minor, "ReplyMode");
    qmlRegisterType<Dekko::SubmissionManager>(uri, major, minor, "SubmissionManager");
    qmlRegisterType<Dekko::Recipient>(uri, major, minor, "Recipient");
    qmlRegisterType<Dekko::Recipients>(uri, major, minor, "Recipients");
    qmlRegisterType<Dekko::RecipientsFilterModel>(uri, major, minor, "RecipientsFilterModel");
    qmlRegisterType<Dekko::MsgComposer>(uri, major, minor, "MsgComposer");
}

void DekkoGlobal::registerDekkoExperimental(int major, int minor)
{
    // @uri Dekko.Experimental
    const char* uri = "Dekko.Experimental";
    qmlRegisterType<Dekko::Notifications::NotificationService>(uri, major, minor, "NotificationService");
    qmlRegisterType<OnlineAccountsService>(uri, major, minor, "OnlineAccountsService");
}

void DekkoGlobal::registerDekkoTheme(int major, int minor)
{
    // @uri Dekko.Theme
    const char* uri = "Dekko.Theme";
    qmlRegisterSingletonType<Dekko::Themes::Theme>(uri, major, minor, "Style", Dekko::Themes::Theme::factory);
}
